# /*
#  * @Author: 周梦泽 
#  * @Date: 2023-03-20 08:48:10 
#  * @Last Modified by:   周梦泽 
#  * @Last Modified time: 2023-03-20 08:48:10 
#  */
# 此模块用于登录淘宝
import time
import traceback

import backoff

from autoTask.operaitonAid.utils.custom_errors import LoginError
from common.utils.web_page_util import create_page
from DrissionPage import WebPage
from common.utils.web_page_util import MockTap, Input, random_delay
from common.logger.log import log_
from autoTask.taobao.sycm.utils.close_Ad import tb_slider

# 首页
taobao_url = "https://www.taobao.com/"
# 注销登录页
taobao_logout_url = "https://login.taobao.com/member/logout.jhtml"
# 千牛/天猫后台
qn_home_url = "https://myseller.taobao.com"


class Login:
    """
    登录淘宝模块
    """

    def __init__(self, account: str, password: str, page: WebPage = None):
        self.account = account
        self.password = password
        self.page = page
        self.is_login = False

    @backoff.on_exception(backoff.constant, Exception, max_tries=3,
                          interval=5, on_backoff=lambda details: log_.error(traceback.format_exc()),
                          giveup=lambda ex: isinstance(ex, LoginError))
    @backoff.on_predicate(backoff.fibo, lambda e: isinstance(e, (LoginError,)), max_tries=1)
    def execute(self, url: str = None):
        """
        执行登录
        :page: 操作网页对象
        :param url: 登录成功后跳转的url
        :return:page: 操作网页对象 store_name: 店铺名称
        """
        log_.info('开始登录')
        page = self.page
        if page is None:
            page = create_page(url=taobao_url, mode='d')
        else:
            if page.url != taobao_url:
                page.get(taobao_url)
                page.handle_alert(accept=True)

        page = self.pre_login_check(page)
        # 账号登陆前的检查
        if not self.is_login:
            self.login_page_actions(page)
            # 登录操作
            page = self.account_check(page, self.account)
            # 登录是否成功检查
            if not self.is_login:
                raise Exception('登录失败')
            log_.info('登录成功')
        store_name = self.get_store_name(page)
        log_.info(f'店铺:{store_name}')
        if url:
            # 登录成功后跳转到指定页面
            random_delay((2, 4))
            if page.url != url:
                page.get(url)
                page.handle_alert(accept=True)
        return page, store_name

    @staticmethod
    def get_store_name(page: WebPage):
        if qn_home_url not in page.url:
            page.get(qn_home_url)
        store_name_ele = page("x://div[contains(@class, 'UserArea--shopName')]")
        return store_name_ele.text

    def login_page_actions(self, page: WebPage):
        """
        登录页的操作
        :param page:页面操作对象
        :return:
        """
        page_account = page.ele('x://*[@id="fm-login-id"]')
        Input(ele=page_account, vals=self.account, msg='输入账号失败', before_delay=(1, 3))()
        Input(ele='x://*[@id="fm-login-password"]', vals=self.password, msg='输入账号失败', before_delay=(1, 3))(page)
        # 滑块验证
        tb_slider(page, timeout=6)
        MockTap(ele='x://*[@id="login-form"]/div[4]/button', msg='点击登录失败', before_delay=(3, 6))(page)
        # tb_slider(page, timeout=4)
        time.sleep(1)
        if page("x://div[@class='login-error-msg']"):
            if "密码" in page("x://div[@class='login-error-msg']").text:
                log_.error('账号名或登录密码不正确')
                raise LoginError('账号名或登录密码不正确')

    def account_check(self, page: WebPage, account) -> (WebPage, int):
        """
        账号检查是否登录成功
        :param account: 账号名
        :param page:页面操作对象
        :return:
        """
        # 查找登录按钮并点击登录
        for _ in range(2):
            # 查找两次
            iframe = page.get_frame("x://div/iframe", timeout=1)
            if iframe:
                if '短信' in iframe("x://div[@class='checkcode-warp']/button").text:
                    log_.info("号码:" + iframe("x://div[@class='ui-form-text']").text)
                    # 如果遇到需要验证码则报错
                    raise LoginError('登录失败，需要验证码')
            elif page(account):
                self.is_login = True
                return page
        raise Exception('登录失败, 未知错误')

    def pre_login_check(self, page: WebPage) -> (WebPage, int):
        """
        子账号登陆前的检查
        检查是否已登录未登录则执行登录
        status 0:未登录 1:已登录 2:账号不对应
        :param page:页面对象
        :return:page, status
        """
        login_box = page("x://li[contains(@class, 'site-nav-login')]/div[@class='site-nav-menu-hd']", timeout=5)
        log_.info(login_box.text)
        if "请登录" in login_box.text:
            self.is_login = False
            MockTap(ele=login_box('tx:请登录'), msg='点击跳转登录页失败', before_delay=(2, 4), reduce_scope=(10, 5))(
                page)
        else:
            # 已登录,检查是否是目标账号
            if self.account != login_box("x://div[@class='site-nav-user']/a", timeout=5).text:
                log_.warning('账号不对应，正切换目标账号')
                page.get(taobao_logout_url)
                self.is_login = False
            else:
                log_.info('已登录')
                self.is_login = True
                if qn_home_url not in page.url:
                    page.get(qn_home_url)
                    page.handle_alert(accept=True)
        return page


if __name__ == '__main__':
    page_, store_name_ = Login(account="中山杰特电器:星星", password="yzt123456").execute()
